home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1996 September / JCSM Shareware Collection (JCS Distribution) (September 1996).ISO / prgtools / euphor13.zip / IMAGE.E < prev    next >
Text File  |  1995-04-27  |  10KB  |  348 lines

  1. -- read a bitmap (.BMP) file into a 2-d sequence of sequences
  2.  
  3. include graphics.e
  4.  
  5. constant BMPFILEHDRSIZE = 14
  6. constant OLDHDRSIZE = 12, NEWHDRSIZE = 40
  7. constant EOF = -1
  8.  
  9. -- error codes returned by read_bitmap()
  10. global constant BMP_OPEN_FAILED = 1,
  11.         BMP_UNEXPECTED_EOF = 2,
  12.         BMP_UNSUPPORTED_FORMAT = 3
  13.      
  14. integer fn, error_code
  15.  
  16. function get_word()
  17.     integer lower, upper
  18.     
  19.     lower = getc(fn)
  20.     upper = getc(fn)
  21.     if upper = EOF then
  22.     error_code = BMP_UNEXPECTED_EOF
  23.     end if
  24.     return upper * 256 + lower
  25. end function
  26.  
  27. function get_dword()
  28.     integer lower, upper
  29.     
  30.     lower = get_word()
  31.     upper = get_word()
  32.     return upper * 65536 + lower
  33. end function
  34.  
  35. function get_c_block(integer num_bytes)
  36.     sequence s
  37.     
  38.     s = repeat(0, num_bytes)
  39.     for i = 1 to num_bytes do
  40.     s[i] = getc(fn)
  41.     end for
  42.     if s[length(s)] = EOF then
  43.     error_code = BMP_UNEXPECTED_EOF
  44.     end if
  45.     return s
  46. end function
  47.  
  48. function get_rgb(integer set_size)
  49. -- get red, green, blue palette values
  50.     integer red, green, blue
  51.     
  52.     blue = getc(fn)
  53.     green = getc(fn)
  54.     red = getc(fn)
  55.     if set_size = 4 then
  56.     if getc(fn) then
  57.     end if
  58.     end if
  59.     return {red, green, blue}
  60. end function
  61.  
  62. function get_rgb_block(integer num_dwords, integer set_size)
  63. -- reads palette 
  64.     sequence s
  65.  
  66.     s = {}
  67.     for i = 1 to num_dwords do
  68.     s = append(s, get_rgb(set_size))
  69.     end for
  70.     if s[length(s)][3] = EOF then
  71.     error_code = BMP_UNEXPECTED_EOF
  72.     end if
  73.     return s
  74. end function
  75.  
  76. function row_bytes(atom BitCount, atom Width)
  77.     return floor(((BitCount * Width) + 31) / 32) * 4
  78. end function
  79.  
  80. function unpack(sequence image, integer BitCount, integer Width, integer Height)
  81. -- unpack the 1-d byte sequence into a 2-d sequence of pixels
  82.     sequence pic_2d, row, bits
  83.     integer bytes, next_byte, byte
  84.     
  85.     pic_2d = {}
  86.     bytes = row_bytes(BitCount, Width)
  87.     next_byte = 1
  88.     for i = 1 to Height do
  89.     row = {}
  90.     if BitCount = 1 then
  91.         for j = 1 to bytes do
  92.         byte = image[next_byte]
  93.         next_byte = next_byte + 1
  94.         bits = repeat(0, 8)
  95.         for k = 8 to 1 by -1 do
  96.             bits[k] = remainder(byte, 2)
  97.             byte = floor(byte/2)
  98.         end for
  99.         row = row & bits
  100.         end for
  101.     elsif BitCount = 2 then
  102.         for j = 1 to bytes do
  103.         byte = image[next_byte]
  104.         next_byte = next_byte + 1
  105.         bits = repeat(0, 4)
  106.         for k = 4 to 1 by -1 do
  107.             bits[k] = remainder(byte, 4)
  108.             byte = floor(byte/4)
  109.         end for
  110.         row = row & bits
  111.         end for
  112.     elsif BitCount = 4 then
  113.         for j = 1 to bytes do
  114.         byte = image[next_byte]
  115.         row = row & floor(byte/16) & remainder(byte, 16)
  116.         next_byte = next_byte + 1
  117.         end for
  118.     elsif BitCount = 8 then
  119.         row = row & image[next_byte..next_byte+bytes-1]
  120.         next_byte = next_byte + bytes
  121.     else
  122.         error_code = BMP_UNSUPPORTED_FORMAT
  123.         exit
  124.     end if
  125.     pic_2d = prepend(pic_2d, row[1..Width])
  126.     end for
  127.     return pic_2d
  128. end function
  129.  
  130. without warning
  131. global function read_bitmap(sequence file_name)
  132. -- read .bmp file, return {palette,image}   
  133.     atom Size 
  134.     integer Type, Xhot, Yhot, Planes, BitCount
  135.     atom Width, Height, Compression, OffBits, SizeHeader, 
  136.      SizeImage, XPelsPerMeter, YPelsPerMeter, ClrUsed,
  137.      ClrImportant, NumColors
  138.     sequence Palette, Bits, two_d_bits
  139.  
  140.     error_code = 0
  141.     fn = open(file_name, "rb")
  142.     if fn = -1 then
  143.     return BMP_OPEN_FAILED
  144.     end if
  145.     Type = get_word()
  146.     Size = get_dword()
  147.     Xhot = get_word()
  148.     Yhot = get_word()
  149.     OffBits = get_dword()
  150.     SizeHeader = get_dword()
  151.  
  152.     if SizeHeader = NEWHDRSIZE then
  153.     Width = get_dword()
  154.     Height = get_dword()
  155.     Planes = get_word()
  156.     BitCount = get_word()
  157.     Compression = get_dword()
  158.     if Compression != 0 then
  159.         return BMP_UNSUPPORTED_FORMAT
  160.     end if
  161.     SizeImage = get_dword()
  162.     XPelsPerMeter = get_dword()
  163.     YPelsPerMeter = get_dword()
  164.     ClrUsed = get_dword()
  165.     ClrImportant = get_dword()
  166.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 4
  167.     Palette = get_rgb_block(NumColors, 4) 
  168.     
  169.     elsif SizeHeader = OLDHDRSIZE then 
  170.     Width = get_word()
  171.     Height = get_word()
  172.     Planes = get_word()
  173.     BitCount = get_word()
  174.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 3
  175.     SizeImage = row_bytes(BitCount, Width) * Height
  176.     Palette = get_rgb_block(NumColors, 3) 
  177.     else
  178.     return BMP_UNSUPPORTED_FORMAT
  179.     end if
  180.     if Planes != 1 then
  181.     return BMP_UNSUPPORTED_FORMAT
  182.     end if
  183.     Bits = get_c_block(row_bytes(BitCount, Width) * Height)
  184.     close(fn)
  185.     two_d_bits = unpack(Bits, BitCount, Width, Height)
  186.     if error_code then
  187.     return error_code 
  188.     end if
  189.     return {Palette, two_d_bits}
  190. end function
  191. with warning
  192.  
  193. type graphics_point(sequence p)
  194.     return length(p) = 2 and p[1] >= 0 and p[2] >= 0
  195. end type
  196.  
  197. type text_point(sequence p)
  198.     return length(p) = 2 and p[1] >= 1 and p[2] >= 1 
  199.        and p[1] <= 200 and p[2] <= 500 -- rough sanity check
  200. end type
  201.  
  202. global procedure display_image(graphics_point xy, sequence pixels)
  203. -- display a 2-d sequence of pixels at location xy
  204. -- N.B. coordinates are {x, y} with {0,0} at top left of screen
  205. -- and x values increasing towards the right, 
  206. -- and y values increasing towards the bottom of the screen
  207.     for i = 1 to length(pixels) do
  208.     pixel(pixels[i], xy)
  209.     xy[2] = xy[2] + 1
  210.     end for
  211. end procedure
  212.  
  213. global function save_image(graphics_point top_left, graphics_point bottom_right)
  214. -- Save a rectangular region on a graphics screen,
  215. -- given the {x, y} coordinates of the top-left and bottom-right 
  216. -- corner pixels. The result is a 2-d sequence of pixels suitable 
  217. -- for use in display_image() above.
  218.     integer x, width
  219.     sequence save
  220.     
  221.     x = top_left[1]
  222.     width = bottom_right[1] - x + 1
  223.     save = {}
  224.     for y = top_left[2] to bottom_right[2] do
  225.     save = append(save, get_pixel({x, y, width}))
  226.     end for
  227.     return save
  228. end function
  229.  
  230. constant COLOR_TEXT_MEMORY = #B8000,
  231.       MONO_TEXT_MEMORY = #B0000
  232.  
  233. constant M_GET_DISPLAY_PAGE = 28,
  234.      M_SET_DISPLAY_PAGE = 29,
  235.      M_GET_ACTIVE_PAGE = 30,
  236.      M_SET_ACTIVE_PAGE = 31
  237.  
  238. constant BYTES_PER_CHAR = 2
  239.  
  240. type page_number(integer p)
  241.     return p >= 0 and p <= 7
  242. end type
  243.  
  244. global function get_display_page()
  245. -- return current page# mapped to the monitor   
  246.     return machine_func(M_GET_DISPLAY_PAGE, 0)
  247. end function
  248.  
  249. global procedure set_display_page(page_number page)
  250. -- select a page to be displayed
  251.     machine_proc(M_SET_DISPLAY_PAGE, page)
  252. end procedure
  253.  
  254. global function get_active_page()
  255. -- return current page# that screen output is sent to
  256.     return machine_func(M_GET_ACTIVE_PAGE, 0)
  257. end function
  258.  
  259. global procedure set_active_page(page_number page)
  260. -- select a page for screen output
  261.     machine_proc(M_SET_ACTIVE_PAGE, page)
  262. end procedure
  263.  
  264. global procedure display_text_image(text_point xy, sequence text)
  265. -- Display a text image at line xy[1], column xy[2] in any text mode.
  266. -- N.B. coordinates are {line, column} with {1,1} at the top left of screen
  267. -- Displays to the active text page. Image must fit on screen.
  268.     atom screen_memory, scr_addr
  269.     integer screen_width, extra_col2, extra_lines
  270.     sequence vc
  271.     
  272.     vc = video_config()
  273.     if vc[VC_MODE] = 7 then
  274.     screen_memory = MONO_TEXT_MEMORY
  275.     else
  276.     screen_memory = COLOR_TEXT_MEMORY
  277.     end if
  278.     screen_width = vc[VC_COLUMNS]
  279.     if screen_width = 40 then
  280.     screen_memory = screen_memory + get_active_page() * 2048
  281.     else
  282.     screen_memory = screen_memory + get_active_page() * 4096
  283.     end if
  284.     
  285.     if xy[1] < 1 or xy[2] < 1 then
  286.     return -- bad starting point
  287.     end if
  288.     extra_lines = vc[VC_LINES] - xy[1] + 1 
  289.     if length(text) > extra_lines then
  290.     if extra_lines <= 0 then
  291.         return -- nothing to display
  292.     end if
  293.     text = text[1..extra_lines] -- truncate
  294.     end if
  295.     scr_addr = screen_memory + (xy[1]-1) * screen_width * BYTES_PER_CHAR
  296.                  + (xy[2]-1) * BYTES_PER_CHAR
  297.     extra_col2 = 2 * (vc[VC_COLUMNS] - xy[2] + 1) 
  298.     for row = 1 to length(text) do
  299.     if length(text[row]) > extra_col2 then
  300.         if extra_col2 <= 0 then
  301.         return -- nothing to display
  302.         end if
  303.         text[row] = text[row][1..extra_col2] -- truncate
  304.     end if
  305.     for col = 0 to length(text[row])-1 do
  306.         poke(scr_addr+col, text[row][col+1])
  307.     end for
  308.     scr_addr = scr_addr + screen_width * BYTES_PER_CHAR
  309.     end for
  310. end procedure
  311.  
  312. global function save_text_image(text_point top_left, text_point bottom_right)
  313. -- Copy a rectangular block of text out of screen memory,
  314. -- given the coordinates of the top-left and bottom-right corners.
  315. -- Reads from the active text page.
  316.     sequence image, row_chars, vc
  317.     atom scr_addr, screen_memory
  318.     integer screen_width, image_width
  319.     
  320.     vc = video_config()
  321.     if vc[VC_MODE] = 7 then
  322.     screen_memory = MONO_TEXT_MEMORY
  323.     else
  324.     screen_memory = COLOR_TEXT_MEMORY
  325.     end if
  326.     screen_width = vc[VC_COLUMNS]
  327.     if screen_width = 40 then
  328.     screen_memory = screen_memory + get_active_page() * 2048
  329.     else
  330.     screen_memory = screen_memory + get_active_page() * 4096
  331.     end if
  332.     scr_addr = screen_memory + 
  333.            (top_left[1]-1) * screen_width * BYTES_PER_CHAR + 
  334.            (top_left[2]-1) * BYTES_PER_CHAR
  335.     image = {}
  336.     image_width = bottom_right[2] - top_left[2] + 1
  337.     for row = top_left[1] to bottom_right[1] do
  338.     row_chars = {}
  339.     for col = 0 to image_width*BYTES_PER_CHAR-1 do
  340.         row_chars = row_chars & peek(scr_addr + col)
  341.     end for
  342.     image = append(image, row_chars)
  343.     scr_addr = scr_addr + screen_width * BYTES_PER_CHAR
  344.     end for
  345.     return image
  346. end function
  347.  
  348.